﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MIAP.DataAccess.Implementaciones.SQL;
using MIAP.DataAccess.Interfaces;
using MIAP.Entidades;
using MIAP.Entidades.Enums;

namespace MIAP.Negocio
{
    /// <summary>
    /// Clase de negocio para la vista EjecucionProyecto.
    /// </summary>
    public class EjecucionProyectosNegocio
    {
        #region Campos

        /// <summary>
        /// Instancia para el acceso a datos de EjecutaProyecto.
        /// </summary>
        private readonly IEjecutaProyectoDao daoEjecutaProyecto;

        /// <summary>
        /// Instancia para el acceso a datos de EjecutaProyecto.
        /// </summary>
        private readonly IProyectosDao daoProyecto;

        /// <summary>
        /// Instancia para el acceso a datos de ActualizaVersionValida
        /// </summary>
        private readonly IActualizaVersionDao daoActualizaVersion;

        /// <summary>
        /// Instancia para las operaciones de negocio comunes a la aplicación.
        /// </summary>
        private ComunesNegocio comunesNegocio;

        /// <summary>
        /// instanciapara el acceso a datos de archivos
        /// </summary>
        private readonly IArchivosDao daoArchivos;

        #endregion

        #region Constructor

        /// <summary>
        /// Inicializa una instancia de <see cref="EjecucionProyectosNegocio"/>
        /// </summary>
        public EjecucionProyectosNegocio()
        {
            this.daoEjecutaProyecto = DataAccessFactory.Instance.CreateEjecutaProyectoDao();
            this.comunesNegocio = new ComunesNegocio();
            this.daoProyecto = DataAccessFactory.Instance.CreateProyectosDao();
            this.daoActualizaVersion = DataAccessFactory.Instance.CreateActualizacionVersionDao();
            this.daoArchivos = DataAccessFactory.Instance.CreateArchivosDao();
        }

        #endregion

        /// <summary>
        /// Obtiene todos los archivos obligatorios.
        /// </summary>
        /// <param name="archivoAsociadoFilters">Filtros para obtener los archivos obligatorios.</param>        
        /// <param name="esObligatorio">Indica si se buscan archivos obligatorios o no</param>
        /// <returns>Lista con los archivos obligatorios de acuerdo a los filtros.</returns>
        public List<ArchivoAsociadoProyectoInfo> GetArchivosObligatoriosAndNoObligatorios(ArchivoAsociadoProyectoInfo archivoAsociadoFilters, bool esObligatorio)
        {
            var listaArchivos = this.daoArchivos.GetArchivos(null, archivoAsociadoFilters.IdProyecto, null,
                                                             esObligatorio, null, true);
            var retorno= this.daoEjecutaProyecto.GetArchivosObligatoriosAndNoObligatorios(archivoAsociadoFilters, esObligatorio).ToList();

            foreach (var archivo in listaArchivos.Where(archivo => retorno.All(elemento => elemento.IdArchivo != archivo.IdentificadorArchivo)))
            {
                retorno.Add(new ArchivoAsociadoProyectoInfo()
                    {
                        IdArchivo = archivo.IdentificadorArchivo,
                        NombreArchivo = archivo.NombreArchivo,
                        NombreProyecto = archivo.Proyecto.NombreProyecto,
                        Carga = "NO",
                        Version = archivo.EsVersionable ? "SI" : "NO",
                        Versionable = archivo.EsVersionable
                    });
            }
            return retorno;
        }

        /// <summary>
        /// Obtiene todas las cargas y recargas de archivos realizadas de acuerdo a los filtros.
        /// </summary>
        /// <param name="archivoAsociadoFilters">Filtros para la búsqueda.</param>
        /// <returns>Lista con las cargas y recargas de archivos.</returns>
        public List<ArchivoCargadoInfo> GetCargasRealizadasByPeriodo(ArchivoAsociadoProyectoInfo archivoAsociadoFilters)
        {
            List<ArchivoCargadoInfo> listCargasRealizadas;

            listCargasRealizadas = this.daoEjecutaProyecto.GetCargasRealizadasByPeriodo(archivoAsociadoFilters).ToList();

            List<ArchivoCargadoInfo> listCargasRealizadasByArchivo = ComunesNegocio.GetArchivoWithLastProcess(listCargasRealizadas);
            
            List<CatalogoInfo> listArchivosCarga = new List<CatalogoInfo>();            

            foreach (ArchivoCargadoInfo archivo in listCargasRealizadasByArchivo)
            {
                listArchivosCarga.Add(new CatalogoInfo { IdItem = archivo.IdCargaArchivo, Descripcion = archivo.Version });                
            }

            if (listArchivosCarga.Count != default(int))
            {
                // Obtener los autorizadores.
                List<EjecutorInfo> listAutorizadores = this.comunesNegocio.GetAutorizador(listArchivosCarga).ToList();

                foreach (EjecutorInfo autorizador in listAutorizadores)
                {
                    listCargasRealizadasByArchivo.Where(p => p.IdCargaArchivo == autorizador.IdCargaArchivo && p.Version == autorizador.VersionArchivo).Single().Autorizador = autorizador.NombreEjecutor;                    
                }
            }

            // Obtener los versionadores.
            List<CatalogoInfo> listVersionadores = this.comunesNegocio.GetNombreVersionador(listArchivosCarga).ToList();

            foreach (CatalogoInfo versionador in listVersionadores)
            {
                listCargasRealizadasByArchivo.Where(p => p.IdCargaArchivo == versionador.IdItem).Single().NombreEjecutorCarga = versionador.Descripcion;
            }           

            return listCargasRealizadasByArchivo;
        }

        /// <summary>
        /// Registra la ejecucion del proyecto en la base de datos
        /// </summary>
        /// <param name="proyecto">proyecto que ejecutaremos</param>
        /// <param name="user">usuaio al que se le registrará le ejecucion</param>
        public int EjecutaProyecto(ListaInfo proyecto, UsuarioInfo user)
        {
           return this.daoEjecutaProyecto.EjecutaProyecto(proyecto,user);
        }

        /// <summary>
        /// Obtiene la información de un determinado proyecto.
        /// </summary>
        /// <param name="idProyecto">Es el id del proyecto del que se desea obtener la informacion.</param>
        /// <returns>Información general del usuario.</returns>
        public ProyectoInfo GetProyectoById(int idProyecto)
        {
            return this.daoProyecto.GetProyectoById(idProyecto);
        }

        /// <summary>
        /// Obtiene el nombre de la versión válida del archivo.
        /// </summary>
        /// <param name="idArchivo">Es el id del archivo del cual se dese obtener la versión válida.</param>
        /// <returns></returns>
        public string GetNombreVersionValidaArchivo(int idArchivo)
        {
            return this.daoActualizaVersion.GetNombreVersionValidaArchivo(idArchivo);
        }

        /// <summary>
        /// validamos si ya existe una ejecucion en curso para ese proyecto
        /// </summary>
        /// <param name="idproyecto">id del proyecto a verificar</param>
        /// <param name="año">Año del proyecto a verificar</param>
        /// <param name="mes">mes del proyecto a verificar</param>
        /// <returns>true si existe una ejecucion en proceso, false en caso contrario</returns>
        public bool ValidaEjecucionEnProceso(int idproyecto, int año, int mes)
        {
            var filtros = new ConsultaEjecucionProyectoInfo(){Año = año,Mes = mes};

            var listaEjecuciones = new ConsultaEjecucionProyectoNegocio().GetEjecucionProyectosByPeriodo(filtros);
            return
                listaEjecuciones.Any(
                    elemento => elemento.IdProyecto == idproyecto && elemento.IdEstatus == (int) EstatusProceso.Inicio);

        }
    }
}
